home *** CD-ROM | disk | FTP | other *** search
/ Compendium Deluxe 1 / LSD Compendium Deluxe 1.iso / a / disk / backuputils / stow07b.lha / stow.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-11-17  |  26.3 KB  |  660 lines

  1. /*****************************************************************************/
  2. /** Program: Stow        Version: 0.7ß                                      **/
  3. /** Date: November 1993                                                     **/
  4. /** Author: Leonard D Atkinson II                                           **/
  5. /**                                                                         **/
  6. /** Purpose:  Stow examines a given pathname for files and then copies      **/
  7. /**           those files to a device, volume by volume, with the lease     **/
  8. /**           ammount of waste of space.  It optionally outputs a list of   **/
  9. /**           what volumes hold what files.                                 **/
  10. /**                                                                         **/
  11. /** Requires: LIST, COPY, FORMAT commands somewhere in the path.            **/
  12. /**                                                                         **/
  13. /** This source copyright 1993 by Leonard D Atkinson II                     **/
  14. /*****************************************************************************/
  15.  
  16.  
  17. /****************************/
  18. /* INCLUDES                 */
  19. /****************************/
  20. #include <stdio.h>
  21. #include <stdlib.h>
  22. #include <time.h>             /*so we can make unique filename*/
  23. #include <libraries/dos.h>    /*for the checking disk space*/
  24. #include <exec/memory.h>      /*for AllocMem()*/
  25. #include "ansi.h"             /*My own ansi macros*/
  26.  
  27. /****************************/
  28. /* Data Types               */
  29. /****************************/
  30. struct my_file_node {         /*For putting files into linked list*/
  31.      char filename[40];
  32.      long filesize;
  33.      struct my_file_node *next;
  34.      };
  35.  
  36. FILE *fp; /*Generic file point for reading temp file*/
  37.           /*and writing to the output file          */
  38. /****************************/
  39. /* functions                */
  40. /****************************/
  41. long check_free_space(char *); /*Returns the free space on the given volume*/
  42. void bad_format(); /*sends user format and exits*/
  43. void set_num(); /*changes the integer into ABC form*/
  44. void set_format();/*sets first arg to string to append to format call*/
  45. void my_system();/*execute system call with error checking*/
  46. void verify_file();/*checks given filesize to copied filesize*/
  47. void cat_files();/*tack arg2 onto arg3*/
  48.  
  49. /*****************************************************************************/
  50. /* Main                                                                      */
  51. /*****************************************************************************/
  52. main(int argc, char *argv[]) {
  53.  
  54.      /****************************/
  55.      /* Variables                */
  56.      /****************************/
  57.      char filename[40],   /*global filename, for reading into*/
  58.           dos_input[80],      /*Working strings*/
  59.           temp_file_name[80];
  60.      long filesize = 0;   /*global filesize, for reading into*/
  61.      long total = 0;      /*total bytes tally*/
  62.  
  63.      struct my_file_node *head, /*Pointers to linked list*/
  64.                          *temp, 
  65.                          *temp2;
  66.  
  67.      char keep_going;  /*boolean for the main loop*/
  68.  
  69.      int volume_num = 0; /*counter of number of volumes used*/
  70.      int count,i; /*generic count variable*/
  71.      char list_output[40] = "";/*name of list of files copied.*/
  72.      char input_dir[40] = "";/*input directory to be copied from*/
  73.  
  74.      int assumed_size = 842*1024;
  75.      int current_disk;
  76.      int check_size;
  77.      char output_device[40] = "";
  78.      char output_script[40] = "";
  79.      char fixed_size = 0;
  80.      int max_waste = 20000;
  81.      char use_max_waste = 0;
  82.      char archive_name[40] = "STOW_";
  83.      char format_options[40] = "";
  84.      char verify_copies = 0;
  85.      char quiet_output = 0;
  86.      char list_sort = 1;
  87.      char current_diskname[4] = "";
  88.  
  89.      /***********************************************************/
  90.      /* Parse command line arguments                            */
  91.      /***********************************************************/
  92.      for(count = 1; count < argc; count++) {
  93.           if(argv[count][0] == '-') {
  94.                switch(argv[count][1]) {
  95.                     case 'i':/*input directory*/
  96.                     case 'I':
  97.                          strcpy(input_dir,&argv[count][2]);
  98.                          break;
  99.                     case 'o':
  100.                     case 'O':
  101.                          strcpy(list_output,&argv[count][2]);
  102.                          break;
  103.                     case 'a':
  104.                     case 'A':
  105.                          if(strlen(argv[count]) > 2){
  106.                               assumed_size = atoi(&argv[count][2]);
  107.                               assumed_size *= 1024;
  108.                               }
  109.                          fixed_size = 1;
  110.                          current_disk = assumed_size;
  111.                          break;
  112.                     case 'd':
  113.                     case 'D':
  114.                          strcpy(output_device,&argv[count][2]);
  115.                          break;
  116.                     case 'm':
  117.                     case 'M':
  118.                          use_max_waste = 1;
  119.                          if(strlen(argv[count]) > 2){
  120.                               max_waste = atoi(&argv[count][2]);
  121.                               max_waste *= 1024;
  122.                               }
  123.                          break;
  124.                     case 's':
  125.                     case 'S':
  126.                          strcpy(output_script,&argv[count][2]);
  127.                          break;
  128.                     case 'n':
  129.                     case 'N':
  130.                          strncpy(archive_name,&argv[count][2],16);
  131.                          strcat(archive_name,"_");
  132.                          /*turn all non-printables into underscores*/
  133.                          for(i = 0; i<strlen(archive_name); i++)
  134.                               if(isspace(archive_name[i])) archive_name[i] = '_';
  135.                          break;
  136.                     case 'f':
  137.                     case 'F':
  138.                          /*if options are provided, do it, else just put*/
  139.                          /*a space in there for signaling purposes*/
  140.                          if(argv[count][2] != NULL) {
  141.                               set_format(format_options,&(argv[count][2]));
  142.                               }
  143.                          else {
  144.                               strcpy(format_options," ");
  145.                               }
  146.                          break;
  147.                     case 'v':
  148.                     case 'V':
  149.                          verify_copies = 1;
  150.                          break;
  151.                     case 'q':
  152.                     case 'Q':
  153.                          quiet_output = 1;
  154.                          break;
  155.                     case 'l':
  156.                     case 'L':
  157.                          list_sort = 0;
  158.                          break;
  159.                     default:
  160.                          bad_format();
  161.                     }
  162.                }
  163.           else bad_format();
  164.           }
  165.  
  166.      if((strlen(output_device) == 0) || (strlen(input_dir) == 0)) bad_format();
  167.  
  168.      if((strlen(output_script) > 0) && (fixed_size != 1)) {
  169.           printf("Output scripts require an assumed size.\n");
  170.           printf("Auto-enabling an assumed size of %d.\n",assumed_size);
  171.           fixed_size = 1;
  172.           current_disk = assumed_size;
  173.           }
  174.  
  175.      if(quiet_output != 1) printf("Assembling the list of files to be stowed.\n");
  176.  
  177.      /***********************************************************/
  178.      /*Call the LIST command to make a list of all the files    */
  179.      /*name the file with current time afterwards to avoid      */
  180.      /*two versions of the program from clobbering each other's */
  181.      /*temp files.                                              */
  182.      /***********************************************************/
  183.      sprintf(temp_file_name, "t:stow%d", (unsigned int)time(NULL));
  184.      sprintf(dos_input, "list %s %s >%s", input_dir, "lformat \"%S %L\"", temp_file_name );
  185.      my_system(dos_input,"Can't create file list in temp!");     
  186.  
  187.      fp = fopen(temp_file_name,"r");  /*open the file just created*/
  188.      if(fp == NULL) {
  189.           ChangeColors(YELLOW,BLACK);
  190.           printf("For some reason the temp file can't be opened!\n");
  191.           ChangeColors(RED,BLACK);
  192.           exit(1);
  193.           }
  194.  
  195.      /*Make a head node*/
  196.      head = (struct my_file_node *) AllocMem( sizeof(struct my_file_node),
  197.           MEMF_PUBLIC | MEMF_CLEAR );
  198.      if(head == NULL) {
  199.           ChangeColors(YELLOW,BLACK);
  200.           printf("Couldn't allocate memory!\n");
  201.           ChangeColors(RED,BLACK);
  202.           exit(1);
  203.           }          
  204.      head->next = NULL;
  205.  
  206.      /****************************/
  207.      /* Build Linked List        */
  208.      /****************************/
  209.      while(fscanf(fp, "%s %d",filename,&filesize) != EOF) {/*while more*/
  210.           if((filesize > 0) && (strlen(filename)>0)) {
  211.                             /*only bother making nodes for non-empty files*/
  212.                             /*with valid names                            */
  213.                total += filesize;
  214.                /*make a new node*/
  215.                temp = (struct my_file_node *) 
  216.                     AllocMem( sizeof(struct my_file_node),
  217.                               MEMF_PUBLIC | MEMF_CLEAR );
  218.                if(temp == NULL) {
  219.                     ChangeColors(YELLOW,BLACK);
  220.                     printf("Couldn't allocate memory!\n");
  221.                     ChangeColors(RED,BLACK);
  222.                     exit(1);
  223.                     } 
  224.                strcpy(temp->filename, filename);/*fill with information*/
  225.                temp->filesize = filesize;
  226.  
  227.                temp2 = head;/*Find the right place to insert new node*/
  228.  
  229.                if(list_sort == 1) {
  230.                     while((temp2->next != NULL) && 
  231.                          (((temp2->next)->filesize) > (temp->filesize))) 
  232.                               temp2 = temp2->next;
  233.                     }
  234.                else {
  235.                     /*just add to end of list now*/
  236.                     while(temp2->next != NULL) temp2 = temp2->next;
  237.                     }
  238.  
  239.                /*Insert Node*/
  240.                if(temp2->next == NULL) {
  241.                     temp2->next = temp;
  242.                     temp->next = NULL;
  243.                     }
  244.                else {
  245.                     temp->next = temp2->next;
  246.                     temp2->next = temp;
  247.                     }
  248.                }
  249.           }
  250.      fclose(fp); /*close temp file*/
  251.      if(DeleteFile(temp_file_name) == TRUE) { /*delete temp file*/
  252.           ChangeColors(YELLOW,BLACK);
  253.           printf("For some reason the temp file can't be deleted!\n");
  254.           ChangeColors(RED,BLACK);
  255.           exit(1);
  256.           }
  257.  
  258.       if(strlen(list_output) > 0) { /*if requested, open output file*/
  259.           fp = fopen(list_output,"w");
  260.           if(fp == NULL) {
  261.                ChangeColors(YELLOW,BLACK);
  262.                printf("Error--Cannot open file %s for output.\n",list_output);
  263.                ChangeColors(RED,BLACK);
  264.                exit(1);
  265.                }
  266.           fprintf(fp,"!!! Files Stowed !!!\n");
  267.           fclose(fp);
  268.           }    
  269.      if(strlen(output_script) > 0) { /*if requested, open output script*/
  270.           fp = fopen(output_script,"w");
  271.           if(fp == NULL) {
  272.                ChangeColors(YELLOW,BLACK);
  273.                printf("Error--Cannot open file %s for output.\n",output_script);
  274.                ChangeColors(RED,BLACK);
  275.                exit(1);
  276.                }
  277.           fprintf(fp,"echo Stowing %s from script\n",input_dir);
  278.           fclose(fp);
  279.           }
  280.  
  281.      /***************************************************************/
  282.      /*if the input directory doesn't end in / or : then assume it's*/
  283.      /*a directory and put the / in for later catenation.           */
  284.      /***************************************************************/
  285.      if((input_dir[strlen(input_dir) - 1] != '/') && 
  286.         (input_dir[strlen(input_dir) - 1] != ':')) 
  287.           strcat(input_dir, "/");
  288.           
  289.      if(quiet_output != 1) {
  290.           printf("%d total bytes to be packed.\n",total);
  291.           printf("This will take about %d FFS floppies.\n",(total/890000)+1);
  292.           }
  293.  
  294.      /****************************/
  295.      /* Main Loop                */
  296.      /****************************/
  297.      do {
  298.           set_num(current_diskname,volume_num);/*make new disk name*/
  299.           if(strlen(temp_file_name) != 0) { /*if requested, open output file*/
  300.                fp = fopen(temp_file_name,"a");
  301.                if(fp == NULL) {
  302.                     ChangeColors(YELLOW,BLACK);
  303.                     printf("Error--Cannot open file %s for output.\n",temp_file_name);
  304.                     ChangeColors(RED,BLACK);
  305.                     exit(1);
  306.                     }
  307.                fprintf(fp, "ask \"next disk\"\n");
  308.                fclose(fp);
  309.                }
  310.  
  311.           if(strlen(format_options) != 0) {
  312.                sprintf(dos_input,"FORMAT DRIVE %s NAME %s%s %s",
  313.                          output_device,archive_name,current_diskname, format_options);
  314.                if(strlen(output_script) != 0) { /*if requested, open output file*/
  315.                     fp = fopen(output_script,"a");
  316.                     if(fp == NULL) {
  317.                          ChangeColors(YELLOW,BLACK);
  318.                          printf("Error--Cannot open file %s for output.\n",temp_file_name);
  319.                          ChangeColors(RED,BLACK);
  320.                          exit(1);
  321.                          }
  322.                     fprintf(fp, "%s\n",dos_input);
  323.                     fclose(fp);
  324.                     }
  325.                else {
  326.                     my_system(dos_input,"Can't format disk!\n");
  327.                     }
  328.                }
  329.  
  330.           keep_going = FALSE;
  331.           temp = head->next;
  332.           temp2 = head;
  333.           while(temp != NULL) {
  334.                /*Scan the whole list*/
  335.                if(fixed_size == 1){
  336.                     check_size = current_disk;
  337.                     }
  338.                else {
  339.                     check_size = (check_free_space(output_device) - 3076);
  340.                     }
  341.                if(temp->filesize < check_size) {
  342.                     /**************************************************/
  343.                     /*if the file will fit on the volume, put it there*/
  344.                     /*3K may be a bit large, but 1K is too small      */
  345.                     /*Better safe than sorry, I guess                 */
  346.                     /**************************************************/
  347.  
  348.                     /*Inform user what's going on*/
  349.                     if(quiet_output != 1) {
  350.                          printf("%c                                                %c",13,13);
  351.                          printf("Copying %s",temp->filename);
  352.                          }
  353.  
  354.                     /*assemble dos call to COPY*/
  355.                     sprintf(dos_input, "copy %s%s %s",input_dir,temp->filename,output_device);
  356.                     if(fixed_size == 1) current_disk -= temp->filesize;
  357.                     if(strlen(output_script) > 0) { /*if requested, open output file*/
  358.                          fp = fopen(output_script,"a");
  359.                          if(fp == NULL) {
  360.                               ChangeColors(YELLOW,BLACK);
  361.                               printf("Error--Cannot open file %s for output.\n",list_output);
  362.                               ChangeColors(RED,BLACK);
  363.                               exit(1);
  364.                               }
  365.                          fprintf(fp,"%s\n",dos_input);
  366.                          fclose(fp);
  367.                          }
  368.                     else {
  369.                          my_system(dos_input,"Copy Failed!\n");
  370.                          }
  371.                     if(verify_copies == 1) {
  372.                          sprintf(filename,"%s%s",input_dir,temp->filename);
  373.                          verify_file(filename,temp->filesize);
  374.                          }
  375.                     /*Add filename to output file*/
  376.                     if(strlen(list_output) > 0) { /*if requested, open output file*/
  377.                          fp = fopen(list_output,"a");
  378.                          if(fp == NULL) {
  379.                               ChangeColors(YELLOW,BLACK);
  380.                               printf("Error--Cannot open file %s for output.\n",list_output);
  381.                               ChangeColors(RED,BLACK);
  382.                               exit(1);
  383.                               }
  384.                          fprintf(fp,"%-32.32s %6.6d %s%s\n",temp->filename,temp->filesize,archive_name,current_diskname);
  385.  
  386.                          fclose(fp);
  387.                          }
  388.                     temp2->next = temp->next;/*remove node from list*/
  389.                     FreeMem(temp, sizeof(struct my_file_node));/*delete node*/
  390.                     temp = temp2->next; /*move temp to next in list*/
  391.                     }
  392.  
  393.                else {
  394.                     /*if this file won't fit, try next smaller one*/
  395.                     temp2 = temp;
  396.                     temp = temp->next;
  397.                     }
  398.                }/*end of while list-pointer-not-null loop*/
  399.           if(quiet_output != 1) putchar(13);
  400.  
  401.           if(((use_max_waste == 1) && (current_disk < max_waste)) || (use_max_waste == 0)) {
  402.                if(strlen(output_script) > 0) {
  403.                     cat_files(output_script,temp_file_name);
  404.                     fp = fopen(output_script,"a");
  405.                     if(fp == NULL) {
  406.                          ChangeColors(YELLOW,BLACK);
  407.                          printf("Error--Cannot open file %s for output.\n",list_output);
  408.                          ChangeColors(RED,BLACK);
  409.                          exit(1);
  410.                          }
  411.                     fprintf(fp,"echo disk finished\necho %d bytes free on disk\n",current_disk);
  412.                     fclose(fp);
  413.                     }
  414.                else {
  415.                     printf("Remove the volume in %s and put in another.\n",output_device);
  416.                     printf("Press RETURN");
  417.                     getchar();
  418.                     }
  419.                if(fixed_size == 1) current_disk = assumed_size;
  420.                if(head->next != NULL) keep_going = TRUE;
  421.                }
  422.           volume_num++;/*advance to next volume number*/
  423.           } while(keep_going);
  424.           if(quiet_output != 1) printf("Finished                           \n");
  425.      }/*end of main*/
  426.  
  427.  
  428. /******************************************************************************/
  429. /**check_free_space()                                                        **/
  430. /**Takes the name of a device and returns the bytes free                     **/
  431. /******************************************************************************/
  432. long check_free_space(char *checked_device) {
  433.  
  434.      /*************************/
  435.      /* Variables             */
  436.      /*************************/
  437.      struct FileLock *lock;
  438.      struct InfoData *info_ptr;
  439.      long return_value;
  440.  
  441.      /***********************************/
  442.      /*Get a new InfoData structure     */
  443.      /*AllocMem assures a 4 byte boundry*/
  444.      /***********************************/
  445.      info_ptr = (struct InfoData *) AllocMem( sizeof( struct InfoData ),
  446.           MEMF_PUBLIC | MEMF_CLEAR );
  447.      if( info_ptr == NULL ) {
  448.           ChangeColors(YELLOW,BLACK);
  449.           printf("Couldn't allocate memory!\n");
  450.           ChangeColors(RED,BLACK);
  451.           exit(1);
  452.           }
  453.  
  454.      /*get a file lock*/
  455.      lock = (struct FileLock *) Lock( checked_device, SHARED_LOCK );
  456.      if( lock == NULL ) {
  457.           ChangeColors(YELLOW,BLACK);
  458.           printf("Could not lock your desination device!\n");
  459.           ChangeColors(RED,BLACK);
  460.           FreeMem( info_ptr, sizeof( struct InfoData ) );
  461.           exit(1);
  462.           }
  463.      if( Info( lock, info_ptr ) == NULL ) {
  464.           ChangeColors(YELLOW,BLACK);
  465.           printf("Could not examine your destination device!\n");
  466.           ChangeColors(RED,BLACK);
  467.           FreeMem( info_ptr, sizeof( struct InfoData ) );
  468.           UnLock( lock );  
  469.           exit(1);
  470.           }
  471.  
  472.      /*Set return value*/
  473.      return_value = (info_ptr->id_NumBlocks - info_ptr->id_NumBlocksUsed) 
  474.             * info_ptr->id_BytesPerBlock;
  475.  
  476.      /*Free up the file and memory*/
  477.      UnLock( lock );  
  478.      FreeMem( info_ptr, sizeof( struct InfoData ) );
  479.      
  480.      return(return_value);
  481.      }/*end of check_free_space() */
  482.  
  483. /******************************************************************************/
  484. /**  bad_format                                                              **/
  485. /**  instructs user that a bad format of options was given                   **/
  486. /******************************************************************************/
  487. void bad_format(){
  488.      printf("Usage: stow <-command> <-command> ... <-command>\n\n");
  489.      printf("A[#]        Assume disk size      I<directory> Directory to copy files from\n");
  490.      printf("O<filename> Output list of files  M[max waste] Set 'max waste'\n");
  491.      printf("S<filename> Make script file      D<device>    Output device copied to\n");
  492.      printf("N<name>     Name the archive      Q            Be quiet\n");
  493.      printf("F<options>  Format disks          V            Verify all copies made\n");
  494.      printf("L           Alternate list pack\n");
  495.      exit(1);
  496.      }
  497.  
  498.  
  499. /******************************************************************************/
  500. /**  set_num                                                                 **/
  501. /**  converts int to letter form for naming disks                            **/
  502. /******************************************************************************/
  503. void set_num(char *output, int num) {
  504.  
  505.      output[0] = 'A' + (num/(26*26));
  506.      num -= ((num/(26*26)) * (26*26));
  507.      output[1] = 'A' + (num/(26));
  508.      num -= ((num/(26)) * 26);
  509.      output[2] = 'A' + num;
  510.  
  511.      return;
  512.      }
  513.  
  514. /******************************************************************************/
  515. /** set_format                                                               **/
  516. /** parses the options to the format command                                 **/
  517. /******************************************************************************/
  518. void set_format(char *out, char *in) {
  519.  
  520.      int count = 0;
  521.  
  522.      while(in[count] != NULL) {
  523.           switch(in[count++]) {
  524.                case 'Q':
  525.                case 'q':
  526.                     strcat(out,"QUICK ");
  527.                     break;
  528.                case 'F':
  529.                case 'f':
  530.                     strcat(out,"FFS ");
  531.                     break;
  532.                case 'N':
  533.                case 'n':
  534.                     strcat(out,"NOICONS ");
  535.                     break;
  536.                default:
  537.                     break;
  538.                }
  539.           }
  540.      return;
  541.      }
  542.  
  543. /******************************************************************************/
  544. /** my_system                                                                **/
  545. /** Gets rid of a bunch of repetitive calls to system()                      **/
  546. /******************************************************************************/
  547. void my_system(char *sys_call, char *error_string) {
  548.  
  549.      if(system(sys_call) != 0) {
  550.           ChangeColors(YELLOW,BLACK);
  551.           printf("%s\n",error_string);
  552.           ChangeColors(RED,BLACK);
  553.           exit(1);
  554.           }
  555.      return;
  556.      }
  557.  
  558. /******************************************************************************/
  559. /** Verify_File()                                                            **/
  560. /** Checks actual filesize verses the original                               **/
  561. /******************************************************************************/
  562. void verify_file(char *checked_file, int check_size) {
  563.      /*************************/
  564.      /* Variables             */
  565.      /*************************/
  566.      struct FileLock *lock;
  567.      struct FileInfoBlock *fib_ptr;
  568.  
  569.      /***********************************/
  570.      /*Get a new FileInfoBlock structure*/
  571.      /*AllocMem assures a 4 byte boundry*/
  572.      /***********************************/
  573.      fib_ptr = (struct FileInfoBlock *)
  574.           AllocMem( sizeof( struct FileInfoBlock ),
  575.           MEMF_PUBLIC | MEMF_CLEAR );
  576.      /* Check if we have allocated the memory successfully: */
  577.      if( fib_ptr == NULL ) {
  578.           ChangeColors(YELLOW,BLACK);
  579.           printf("Couldn't allocate memory!\n");
  580.           ChangeColors(RED,BLACK);
  581.           exit(1);
  582.           }
  583.  
  584.      /*get a file lock*/
  585.      lock = (struct FileLock *) Lock( checked_file, SHARED_LOCK );
  586.      if( lock == NULL ) {
  587.           ChangeColors(YELLOW,BLACK);
  588.           printf("Could not lock %s!\n",checked_file);
  589.           ChangeColors(RED,BLACK);
  590.           FreeMem( fib_ptr, sizeof( struct FileInfoBlock ) );
  591.           exit(1);
  592.           }
  593.  
  594.      if( Examine( lock, fib_ptr ) == NULL ) {
  595.           ChangeColors(YELLOW,BLACK);
  596.           printf("Could not examine %s!\n",checked_file);
  597.           ChangeColors(RED,BLACK);
  598.           FreeMem( fib_ptr, sizeof( struct FileInfoBlock ) );
  599.           UnLock( lock );  
  600.           exit(1);
  601.           }
  602.  
  603.      /*Set return value*/
  604.      if(fib_ptr->fib_Size != check_size) {
  605.           ChangeColors(YELLOW,BLACK);
  606.           printf("%s did not verify!\n",checked_file);
  607.           ChangeColors(RED,BLACK);
  608.           FreeMem( fib_ptr, sizeof( struct FileInfoBlock ) );
  609.           UnLock( lock );  
  610.           exit(1);
  611.           }
  612.  
  613.      /*Free up the file and memory*/
  614.      UnLock( lock );  
  615.      FreeMem( fib_ptr, sizeof( struct FileInfoBlock ) );
  616.      
  617.      return;
  618.      }/*end of verify_file() */
  619.  
  620. /******************************************************************************/
  621. /**cat_files()                                                               **/
  622. /**stick the second file onto the end of the first and delete it             **/
  623. /******************************************************************************/
  624. void cat_files(char *start_file, char *end_file) {
  625.  
  626.      FILE *fp1;
  627.      FILE *fp2;
  628.      char c;
  629.  
  630.      fp1 = fopen(start_file,"a");
  631.      if(fp1 == NULL) {
  632.           ChangeColors(YELLOW,BLACK);
  633.           printf("Error--Cannot open file %s for output.\n",start_file);
  634.           ChangeColors(RED,BLACK);
  635.           exit(1);
  636.           }
  637.      fp2 = fopen(end_file,"r");
  638.      if(fp2 == NULL) {
  639.           ChangeColors(YELLOW,BLACK);
  640.           printf("Error--Cannot open file %s for input.\n",end_file);
  641.           ChangeColors(RED,BLACK);
  642.           exit(1);
  643.           }
  644.      c = fgetc(fp2);
  645.      while(c != EOF) {
  646.           fputc(c, fp1);
  647.           c = fgetc(fp2);
  648.           }
  649.      fclose(fp1);
  650.      fclose(fp2);
  651.      if(DeleteFile(end_file) == TRUE) { /*delete temp file*/
  652.           ChangeColors(YELLOW,BLACK);
  653.           printf("For some reason the temp file can't be deleted!\n");
  654.           ChangeColors(RED,BLACK);
  655.           exit(1);
  656.           }
  657.      return;
  658.      }
  659.  
  660.